#pragma once

#include "factory.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>



struct Codec {

  static void gen (u8 key[32]);

  static void nat (Ptr<IpPackage> pkg);
  static Ptr<IpPackage> parse (ByteBuffer<>& buf);
  static bool check (ByteBuffer<> buf, const char* prefix);
  static void print (Ptr<IpPackage> pkg, const char* prefix);

  static ByteBuffer<> encode (ByteBuffer<>& src, jlib::AES& aes, u8 key[32]);
  static ByteBuffer<> decode (ByteBuffer<>& src, jlib::AES& aes, u8 key[32]);
  static ByteBuffer<> encode (ByteBuffer<>& src, jlib::RSA& rsa);
  static ByteBuffer<> decode (ByteBuffer<>& src, jlib::RSA& rsa);



  inline static std::string ipaddr (u32 ip) {
    char buf[64];
    sprintf(buf, "%d.%d.%d.%d", ip >> 24, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
    return buf;
  }

  inline static std::string iptcpaddr (u32 ip, u16 port) {
    char buf[64];
    sprintf(buf, "%d.%d.%d.%d:%d", ip >> 24, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF, port);
    return buf;
  }

  inline static std::string ifaddr (const u8 mac[6]) {
    char buf[64];
    sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return buf;
  }

};
